最新版Mybatis |
您所在的位置:网站首页 › mybatis model › 最新版Mybatis |
前言:现实开发中我们常常会遇到这样一种情况:技术经理要求开发人员创建的每一个表都要有一些公共字段:创建者id、更新者id、创建及更新时间、逻辑删除字段、租户字段等等。 而我们在新增记录或者更新记录的时候往往要频繁处理这些字段,而抽离出来的话,与持久层框架的结合又很不舒服。好在mybatis-plus为我们提供了很好用的自动填充和逻辑删除支持。 思路上次有朋友说他们平时对于持久层的实体类对象,会把公共字段抽出来当一个父类,而不是每一个实体类中都有这些字段,mybatis-plus支持了抽出父类的模式,也支持后面一种模式(笔者用的就是后面一种),因此本篇会两种都讲,主要以前者为主。 mybatis-plus实现自动填充和逻辑删除的逻辑大致是: 实体类中对需要自动填充和逻辑删除的字段做标记配置(交给公共类去实现或者交给代码生成器去实现) 配置全局的自动填充实现代码 配置全局的逻辑删除实现配置 业务代码不需要编写任何公共字段的逻辑 公共Entity方式 表字段首先看一下数据库中涉及的公共字段,逻辑删除一般用tinyint或者boolean(如果支持的话) 上文讲过entity是支持ActiveRecord模式的,放在java项目中,简单来说就是可以直接通过实体来进行增删改查操作,即: mapper.insert(entity) ↓↓↓↓↓↓ entity.insert()而如果我们在代码生成器中设置activeRecord模式为true,那么生成的entity类就会集成mybatis-plus的com.baomidou.mybatisplus.extension.activerecord.Model类。 那么如果我们要给所有的entity设置公共父类用以拓展(比如公共字段这些),就需要继承这个Model类。 即,mybatis-plus的Model为最上级,然后是中间的公共父类,最后是一个个的业务Entity类。 当然,要是不想使用activeRecord模式也就不需要继承Model了,直接一个简单的java类当公共父类即可。 下面是示例的公共entity类代码: import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.extension.activerecord.Model; import lombok.Getter; import lombok.Setter; import java.io.Serializable; import java.time.LocalDateTime; /** * @ClassName EntityCommon * @Description 公共entity类 * @Author Chenyongyu * @Date 2022/1/12 15:19 * @Version 1.0 **/ @Getter @Setter public abstract class EntityCommon extends Model { @TableField(value = "create_id", fill = FieldFill.INSERT) // 创建人id private Long createId; @TableField(value = "create_time", fill = FieldFill.INSERT) // 创建时间 private LocalDateTime createTime; @TableField(value = "update_id", fill = FieldFill.UPDATE) // 更新人id private Long updateId; @TableField(value = "update_time", fill = FieldFill.UPDATE) // 更新时间 private LocalDateTime updateTime; // 逻辑删除 @TableLogic @TableField(value = "deleted") private boolean deleted; public abstract Serializable pkVal(); } Model类中的泛型T用来传递具体实体entity类,这样mybatis-plus才能给持久层传递此类对应的表信息等,因此泛型信息需要层层继承 抽象方法pkVal,具体实体类需要实现此方法,mybatis-plus通过此方法找到实体的主键,比如区分插入还是更新等逻辑 @TableField + fill注解标记自动填充的字段,其中value为对应表字段,fill为填充模式,有INSERT、UPDATE、INSERT_UPDATE这几种模式。比如更新时间这个字段,在新增记录时,有的人习惯也加上更新时间,有的人习惯更新时间为空,这就是UPDATE和INSERT_UPDATE的区别。 @TableLogic标记逻辑删除字段 逻辑删除的配置因为逻辑删除既支持boolean型,也支持字符串、数字型甚至是时间类型,所以我们需要配置删除状态和未删除状态对应的数据库值。这里mysql我们使用的数据库类型为tinyint(1),所以逻辑删除值可以用1与0表示。具体需要配置在application.yaml文件中: mybatis-plus: #...省略其他配置 global-config: db-config: logic-delete-field: deleted # 全局逻辑删除的实体字段名 logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)这样配置的效果是:在新增记录时,默认会给deleted字段赋值0,涉及查询时(update等操作默认的where条件也算),会默认添加deleted=0的条件,即逻辑未删除的记录。执行delete语句时,不会删除记录,只会把记录对应的deleted属性设置为1。 代码生成器最后我们要修改代码生成器中关于entity的策略配置。 一方面,要设置entity的公共父类 另一方,要设置entity生成忽略的字段,即我们分离出去的updateTime,deleted等。 .strategyConfig(builder -> { builder .addInclude("table_4_mp") // 跳过视图的生成 .enableSkipView() .entityBuilder() // (重要)主键模式,这里设置自动模式,配合mysql的自增主键 .idType(IdType.AUTO) // entity文件名,这里配置后面统一加Entity后缀 .formatFileName("%sEntity") // activeRecord模式,使用上来说就是可以直接在entity对象上执行insert、update等操作 .enableActiveRecord() // ###########修改点是下面两条############## // 公共父类 .superClass(EntityCommon.class) // 忽略的列 .addIgnoreColumns("create_time","create_id","update_time","update_id","deleted") .build(); })我们看一眼生成的类: 这一步是实现mybatis-plus自动填充的关键一步,即自定义自动填充具体的业务实现。 新建一个springbean继承MetaObjectHandler接口 实现insertFill和updateFill方法 编写每个字段具体的业务实现 @Component public class AutoFillMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { // 创建时间,取当前时间,也可以自定义 this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 创建人id,这个看自身业务如何获取,我这里是获取的保存在上下文(ThreadLocal)中的用户id this.strictInsertFill(metaObject, "createId", Long.class, UserContext.getUserInfo().get().getUserId()); } @Override public void updateFill(MetaObject metaObject) { // 更新时间,取当前时间,也可以自定义 this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 更新人id,这个看自身业务如何获取,我这里是获取的保存在上下文(ThreadLocal)中的用户id this.strictUpdateFill(metaObject, "updateId", Long.class, UserContext.getUserInfo().get().getUserId()); } }这里稍微说一下strictInsertFill方法和strictUpdateFill方法 MetaObjectHandler strictInsertFill(MetaObject metaObject, String fieldName, Class fieldType, E fieldVal)四个参数分别是: 透传的metaObject对象,即用来插入或修改的表实体类对象,可以在这里读取或修改 字段名,是类字段名,不是表字段名 字段类型,java类型 填充的值,这个就是最关键的我们想要自动填充的业务值,比如当前时间、当前会话代表的用户id、当前所在环境等等 验证到这里,自动填充和逻辑删除的设置就做好了,我们编写一些代码来测试一下: // 模拟会话状态,真正业务环境会在调用controller接口时往会话中加入当前用户id UserInfo userInfo = new UserInfo(); userInfo.setUserId(34112398L); UserContext.getUserInfo().set(userInfo); // 直接用new的实体来insert Table4MpEntity table4MpEntity = new Table4MpEntity(); table4MpEntity.setName("辣椒儿"); table4MpEntity.setAge(28); table4MpEntity.insert(); System.out.println("createTime:"+table4MpEntity.getCreateTime()); System.out.println("updateTime:"+table4MpEntity.getUpdateTime()); // 修改年龄 table4MpEntity.setAge(29); table4MpEntity.updateById(); System.out.println("createTime:"+table4MpEntity.getCreateTime()); System.out.println("updateTime:"+table4MpEntity.getUpdateTime()); // 删除 table4MpEntity.deleteById(); // 再查询 Table4MpEntity table4MpEntitySearch = table4MpMapper.selectById(table4MpEntity.getId()); System.out.println(table4MpEntitySearch == null);结果: createTime:2022-01-17T16:28:33.139 updateTime:null createTime:2022-01-17T16:28:33.139 updateTime:2022-01-17T16:28:35.051 true自动填充和逻辑删除都是有效的。 独立entity方式最后再介绍一下独立entity,即不适用公共的父类的方式,这种方式下createTime、updateId、deleted等在各自的entity类内部,包括各自的注解等。 这种情况下如果手动编写注解,则会面临下次执行代码生成器时自定义的代码被顶掉的问题。 好在mybatis-plus在代码生成器中为我们提供了相关设置: .strategyConfig(builder -> { builder .addInclude("table_4_mp") // 跳过视图的生成 .enableSkipView() .entityBuilder() // (重要)主键模式,这里设置自动模式,配合mysql的自增主键 .idType(IdType.AUTO) // entity文件名,这里配置后面统一加Entity后缀 .formatFileName("%sEntity") // activeRecord模式,使用上来说就是可以直接在entity对象上执行insert、update等操作 .enableActiveRecord() // 添加tableField注解 .enableTableFieldAnnotation() // 自动填充字段 .addTableFills(Arrays.asList( new Column("create_time", FieldFill.INSERT), new Column("create_id", FieldFill.INSERT), new Column("update_time", FieldFill.UPDATE), new Column("update_id", FieldFill.UPDATE) )) // 逻辑删除字段 .logicDeleteColumnName("deleted") .build(); })这里主要修改了enableTableFieldAnnotation、addTableFills、logicDeleteColumnName这三个设置,指定逻辑删除的字段和自动填充的字段。生成后的entity效果: 其他诸如自动填充业务逻辑的配置、逻辑删除的配置文件设置等都是一样的。 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |